package com.freesky.quartz.task;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayUserDtbankDailybillCreateModel;
import com.alipay.api.domain.AlipayUserDtbankDailybillQueryModel;
import com.alipay.api.request.AlipayUserDtbankDailybillCreateRequest;
import com.alipay.api.request.AlipayUserDtbankDailybillQueryRequest;
import com.alipay.api.response.AlipayUserDtbankDailybillCreateResponse;
import com.alipay.api.response.AlipayUserDtbankDailybillQueryResponse;
import com.freesky.biz.activity.domain.TAlipayBill;
import com.freesky.biz.activity.domain.TAlipayBillTask;
import com.freesky.biz.activity.domain.TAlipayRefundBill;
import com.freesky.biz.activity.mapper.AlipayBillTaskMapper;
import com.freesky.biz.pay.config.AliPayConfiguration;
import com.freesky.biz.utils.SeqUtil;
import com.freesky.common.config.ProjectConfig;
import com.freesky.common.core.domain.AjaxResult;
import com.freesky.common.utils.StringUtils;
import com.freesky.framework.web.domain.server.Sys;
import com.freesky.framework.web.service.SendAlarmService;
import com.opencsv.CSVReader;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

@Slf4j
@Component("alipayDtbankDailybillTask")
public class AlipayDtbankDailybillTask {

    private static final Logger logger = LoggerFactory.getLogger(AlipayDtbankDailybillTask.class);

    @Autowired
    private AliPayConfiguration aliPayConfiguration;

    @Autowired
    private AlipayBillTaskMapper alipayBillTaskMapper;

    @Autowired
    private SendAlarmService sendAlarmService;

    private DateTime minDateTime = DateUtil.parse("2021-11-30","yyyy-MM-dd");


//    public void taskProcess() throws Exception {
//        File file = new File("/Users/zhengxiansheng/Documents/trash");
//        if (file.isDirectory()) {
//            File[] files = file.listFiles();
//            for (int i = 0; i < files.length; i++) {
//                String destPath = "/Users/zhengxiansheng/Documents/process/" + FileUtil.getName(files[i].getName());
//                zipDecompressing(files[i], destPath);
//                List<File> fileList = FileUtil.loopFiles(new File(destPath));
//                for (File fileInfo : fileList) {
//                    String name = fileInfo.getName();
//                    log.info("name:" + name);
//                    if(name.startsWith("日账单_退回明细")){
//                        readRefundList(fileInfo);
//                    }
//                }
//            }
//        }
//    }


    public void taskProcess() {
        DateTime yesterday = DateUtil.offsetDay(new Date(), -1);

        DateTime startTime;
        TAlipayBillTask latestBillTask = alipayBillTaskMapper.selectLatestBillTask();
        if(latestBillTask==null){
            startTime = minDateTime;
        } else {
            log.info("endTIme:"+latestBillTask.getEndTime());
            startTime = DateUtil.parse(latestBillTask.getEndTime(),"yyyy-MM-dd");
        }
        log.info("startTime:"+DateUtil.format(startTime,"yyyy-MM-dd"));

        int generalNum = 0;
        //按一个月一个周期
        while(startTime.isBefore(yesterday)){
            TAlipayBillTask alipayBillTask = new TAlipayBillTask();
            alipayBillTask.setId(SeqUtil.getSeqId());

            startTime = DateUtil.offsetDay(startTime, 1);
            String billQryStartTime = DateUtil.format(startTime,"yyyy-MM-dd");

            if(startTime.isAfter(yesterday)){
                log.info("startTime is After yesterday:"+billQryStartTime);
                break;
            }

            String billQryEndTime = "";
            startTime = DateUtil.offsetDay(startTime,30);
            if(startTime.isAfter(yesterday)){
                billQryEndTime = DateUtil.format(yesterday,"yyyy-MM-dd");
            } else {
                billQryEndTime = DateUtil.format(startTime,"yyyy-MM-dd");
            }
            alipayBillTask.setStartTime(billQryStartTime);
            alipayBillTask.setEndTime(billQryEndTime);

            log.info(JSON.toJSONString(alipayBillTask));
            AjaxResult ajaxResult = createDailyBill(billQryStartTime,billQryEndTime);
            if(!ajaxResult.isSuccess()){
                break;
            }
            alipayBillTask.setBillApplicationId(ajaxResult.get("data").toString());
            alipayBillTask.setProcessed("1");
            alipayBillTaskMapper.addBillTask(alipayBillTask);
            //startTime = DateUtil.offsetDay(startTime, 1);
            generalNum = generalNum + 1;
        }

        if(generalNum>0){
            return;
        }

        TAlipayBillTask alipayQryBillTask = new TAlipayBillTask();
        alipayQryBillTask.setProcessed("1");
        List<TAlipayBillTask> alipayBillTaskList = alipayBillTaskMapper.selectBillTaskList(alipayQryBillTask);

        for(TAlipayBillTask alipayBillTask : alipayBillTaskList){
            AjaxResult ajaxResult = queryDailyBillQuery(alipayBillTask);
            if(!ajaxResult.isSuccess()){
                continue;
            }
            try {
                String billDownloadUrl = ajaxResult.get("data").toString();
                String downloadPath = ProjectConfig.getDownloadPath() + "/alipay/" + alipayBillTask.getBillApplicationId() + ".zip";
                String destPath = ProjectConfig.getDownloadPath() + "/alipay/" + alipayBillTask.getBillApplicationId();
                File downloadFile = new File(downloadPath);
                HttpUtil.downloadFile(billDownloadUrl, downloadFile);

                zipDecompressing(downloadFile, destPath);
                List<File> fileList = FileUtil.loopFiles(new File(destPath));
                for (File file : fileList) {
                    String name = file.getName();
                    log.info(name);
                    if(name.startsWith("日账单_核销明细")){
                        readBillList(file);
                    } else if(name.startsWith("日账单_退回明细")){
                        readRefundList(file);
                   }
                }
                alipayBillTask.setFilePath(downloadPath);
                alipayBillTask.setProcessed("2");
                alipayBillTaskMapper.updateBillTask(alipayBillTask);
            } catch (Exception ioe){
                ioe.printStackTrace();
                log.error(ioe.getMessage());
            }
        }
    }

    public AjaxResult createDailyBill(String startTime,String endTime) {
        try {
            CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
            certAlipayRequest.setServerUrl(aliPayConfiguration.getGatewayUrl());
            certAlipayRequest.setAppId(aliPayConfiguration.getAppId());
            certAlipayRequest.setPrivateKey(aliPayConfiguration.getPrivateKey());
            certAlipayRequest.setFormat("json");
            certAlipayRequest.setCharset(aliPayConfiguration.getCharset());
            certAlipayRequest.setSignType(aliPayConfiguration.getSignType());
            certAlipayRequest.setCertPath(aliPayConfiguration.getAppCertPath());
            certAlipayRequest.setAlipayPublicCertPath(aliPayConfiguration.getAlipayCertPath());
            certAlipayRequest.setRootCertPath(aliPayConfiguration.getAlipayRootCertPath());
            DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);

            AlipayUserDtbankDailybillCreateRequest request = new AlipayUserDtbankDailybillCreateRequest();
            AlipayUserDtbankDailybillCreateModel model = new AlipayUserDtbankDailybillCreateModel();

            // 设置开始时间
            model.setStartTime(DateUtil.parse(startTime,"yyyy-MM-dd"));

            // 设置结束时间
            model.setEndTime(DateUtil.parse(endTime,"yyyy-MM-dd"));

            // 设置账单类型
            model.setBillType("ALL");

            request.setBizModel(model);
            AlipayUserDtbankDailybillCreateResponse response = alipayClient.certificateExecute(request);
            System.out.println(response.getBody());
            if(response.isSuccess()){
                return AjaxResult.success(response.getMsg(),response.getBillApplicationId());
            } else {
                return AjaxResult.error(response.getSubMsg());
            }
        } catch (Exception ioe){
            ioe.printStackTrace();
            logger.error(ioe.getMessage());
            return AjaxResult.error("操作系统，系统异常");
        }

    }

    //String billApplicationId
    public AjaxResult queryDailyBillQuery(TAlipayBillTask alipayBillTask) {
        try {
            CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
            certAlipayRequest.setServerUrl(aliPayConfiguration.getGatewayUrl());
            certAlipayRequest.setAppId(aliPayConfiguration.getAppId());
            certAlipayRequest.setPrivateKey(aliPayConfiguration.getPrivateKey());
            certAlipayRequest.setFormat("json");
            certAlipayRequest.setCharset(aliPayConfiguration.getCharset());
            certAlipayRequest.setSignType(aliPayConfiguration.getSignType());
            certAlipayRequest.setCertPath(aliPayConfiguration.getAppCertPath());
            certAlipayRequest.setAlipayPublicCertPath(aliPayConfiguration.getAlipayCertPath());
            certAlipayRequest.setRootCertPath(aliPayConfiguration.getAlipayRootCertPath());
            DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);


            // 构造请求参数以调用接口
            AlipayUserDtbankDailybillQueryRequest request = new AlipayUserDtbankDailybillQueryRequest();
            AlipayUserDtbankDailybillQueryModel model = new AlipayUserDtbankDailybillQueryModel();

            // 设置日账单申请id
            model.setBillId(alipayBillTask.getBillApplicationId());
            request.setBizModel(model);
            AlipayUserDtbankDailybillQueryResponse response = alipayClient.certificateExecute(request);
            log.info(response.getBody());
            if(response.isSuccess()){
                return AjaxResult.success(response.getMsg(),response.getBillDownloadUrl());
            } else {
                if(!"DAILY_BILL_IS_LOADING".equalsIgnoreCase(response.getSubCode())){
                    alipayBillTask.setProcessed("3");
                    alipayBillTask.setFilePath(response.getSubMsg());
                    alipayBillTaskMapper.updateBillTask(alipayBillTask);
                }
                return AjaxResult.error(response.getSubMsg());
            }

        } catch (Exception ioe){
            ioe.printStackTrace();
            logger.error(ioe.getMessage());
            return AjaxResult.error("操作系统，系统异常");
        }

    }

    /**
     * 解压文件zip
     * @param zipFile 需要解压文件
     * @param descDir 解压完成之后输出的文件夹
     * @throws IOException
     */
    public void zipDecompressing(File zipFile, String descDir) throws IOException {
        try {
            Charset gbk = Charset.forName("gbk");
            ZipInputStream Zin=new ZipInputStream(new FileInputStream(zipFile),gbk);//输入源zip路径
            BufferedInputStream Bin=new BufferedInputStream(Zin);
            String Parent = descDir; //输出路径（文件夹目录）
            File Fout=null;
            ZipEntry entry;
            try {
                while((entry = Zin.getNextEntry())!=null && !entry.isDirectory()){
                    Fout=new File(Parent,entry.getName());
                    if(!Fout.exists()){
                        (new File(Fout.getParent())).mkdirs();
                    }
                    FileOutputStream out=new FileOutputStream(Fout);
                    BufferedOutputStream Bout=new BufferedOutputStream(out);
                    int b;
                    while((b=Bin.read())!=-1){
                        Bout.write(b);
                    }
                    Bout.close();
                    out.close();
                    System.out.println(Fout+"解压成功");
                }

                Bin.close();
                Zin.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            sendAlarmService.sendAlarmMail("250083682@qq.com","【异常】JOB-AlipayDtbankDailybillTask-zipDecompressing",e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 核销明细
     * @param file
     * @return
     */
    public List<TAlipayBill> readBillList(File file){
        System.out.println("readBillList:"+ file.getAbsolutePath());

        long totalCount = 0;
        long totalRows = 0;
        long totalDataSize = 0;
        boolean recordEnd = false;
        DataInputStream in = null;
        InputStreamReader inputStreamReader = null;
        CSVReader reader = null;
        List<TAlipayBill> dataList = new ArrayList<>();
        try {
            in = new DataInputStream(new FileInputStream(file));
            inputStreamReader = new InputStreamReader(in,"utf-8");
            reader = new CSVReader(inputStreamReader);
            String []record = null;
            while ((record = reader.readNext())!=null){
                totalRows = totalRows + 1;
                if(totalRows<=8){
                    continue;
                }
                String rowRecord = record[0].trim();
                System.out.println(rowRecord+","+record.length);
                if(rowRecord.indexOf("明细列表结束")>=0){
                    recordEnd = true;
                }

                if(recordEnd){
                    if(rowRecord.startsWith("#累计核销次数：")) {
                        rowRecord = rowRecord.replaceAll("#累计核销次数：","");
                        rowRecord = rowRecord.replaceAll("笔","");
                        if(StringUtils.isNotEmpty(rowRecord)) {
                            totalCount = Long.parseLong(rowRecord.trim());
                        }
                        break;
                    }
                } else if(record.length>=16){
                    totalDataSize = totalDataSize + 1;
                    TAlipayBill alipayBill = new TAlipayBill();
                    alipayBill.setId(SeqUtil.getSeqId());
                    String stockId = record[0].trim();
                    stockId = stockId.replaceAll(" ","");
                    stockId = stockId.replaceAll("\u200B","");
                    alipayBill.setStockId(stockId);
                    alipayBill.setStockName(record[1].trim());
                    alipayBill.setStockType(record[2].trim());
                    alipayBill.setConsumeTime(record[3].trim());
                    alipayBill.setAmt(record[4].trim());
                    alipayBill.setOrderMoney(record[4].trim());
//                    alipayBill.setOrderMoney(record[5].trim());
//                    alipayBill.setRealMoney(record[6].trim());
//                    alipayBill.setBankNo(record[7].trim());
//                    alipayBill.setTradeNo(record[8].trim());
//                    alipayBill.setMchtId(record[9].trim());
//                    alipayBill.setRechargeMethod(record[10].trim());
//                    alipayBill.setMchtName(record[11].trim());
//                    alipayBill.setStoreId(record[12].trim());
//                    alipayBill.setStoreName(record[13].trim());
//                    alipayBill.setCouponId(record[14].trim());
//                    alipayBill.setCouponTemplate(record[15].trim());
//                    alipayBill.setCardBin(record[16].trim());
                    alipayBill.setRealMoney(record[5].trim());
                    alipayBill.setBankNo(record[6].trim());
                    alipayBill.setTradeNo(record[7].trim());
                    alipayBill.setMchtId(record[8].trim());
                    alipayBill.setRechargeMethod(record[9].trim());
                    alipayBill.setMchtName(record[10].trim());
                    alipayBill.setStoreId(record[11].trim());
                    alipayBill.setStoreName(record[12].trim());
                    alipayBill.setCouponId(record[13].trim());
                    alipayBill.setCouponTemplate(record[14].trim());
                    alipayBill.setCardBin(record[15].trim());
                    dataList.add(alipayBill);

                    if(dataList.size()>10000){
                        alipayBillTaskMapper.addBillBatchOrUpdate(dataList);
                        dataList.clear();
                    }
                }
            }

            if(dataList.size()>0){
                alipayBillTaskMapper.addBillBatchOrUpdate(dataList);
                dataList.clear();
            }

            if(totalCount != totalDataSize){
                sendAlarmService.sendAlarmMail("250083682@qq.com","【异常】JOB-AlipayDtbankDailybillTask，获取核销记录数异常",totalCount + ":"+totalDataSize);
                throw new Exception("获取核销记录数【"+totalCount+"】【"+totalDataSize+"】不符！");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (inputStreamReader != null) {
                    inputStreamReader.close();
                }
                if(reader != null) {
                    reader.close();
                }
            } catch (Exception ioe){

            }
        }
        return dataList;
    }

    /**
     * 退款明细
     * @param file
     * @return
     */
    public List<TAlipayRefundBill> readRefundList(File file){
        long totalCount = 0;
        long totalRows = 0;
        long totalDataSize = 0;
        boolean recordEnd = false;
        DataInputStream in = null;
        InputStreamReader inputStreamReader = null;
        CSVReader reader = null;
        List<TAlipayRefundBill> dataList = new ArrayList<>();
        try {
            in = new DataInputStream(new FileInputStream(file));
            inputStreamReader = new InputStreamReader(in,"utf-8");
            reader = new CSVReader(inputStreamReader);
            String []record = null;
            while ((record = reader.readNext())!=null){
                totalRows = totalRows + 1;
                if(totalRows<=8){
                    continue;
                }
                String rowRecord = record[0].trim();
                System.out.println(rowRecord+","+record.length);
                if(rowRecord.startsWith("#累计核销退回次数")){
                    rowRecord = rowRecord.replaceAll("#累计核销退回次数：","");
                    rowRecord = rowRecord.replaceAll("笔","");
                    if(StringUtils.isNotEmpty(rowRecord)) {
                        totalCount = Long.parseLong(rowRecord.trim());
                    }
                    break;
                }
                if(record.length>=17){
                    totalDataSize = totalDataSize + 1;
                    TAlipayRefundBill alipayRefundBill = new TAlipayRefundBill();
                    alipayRefundBill.setId(SeqUtil.getSeqId());
                    String stockId = record[0].trim();
                    stockId = stockId.replaceAll(" ","");
                    stockId = stockId.replaceAll("\u200B","");
                    alipayRefundBill.setStockId(stockId);
                    alipayRefundBill.setStockName(record[1].trim());
                    alipayRefundBill.setStockType(record[2].trim());
                    alipayRefundBill.setRefundTime(record[3].trim());
                    alipayRefundBill.setConsumeTime(record[4].trim());
                    //红包核销面额
                    alipayRefundBill.setAmt(record[5].trim());
                    //退回金额
                    alipayRefundBill.setRefundAmt(record[6].trim());
                    alipayRefundBill.setOrderMoney(record[7].trim());
                    alipayRefundBill.setRealMoney(record[8].trim());
                    alipayRefundBill.setBankNo(record[9].trim());
                    alipayRefundBill.setTradeNo(record[10].trim());
                    alipayRefundBill.setMchtId(record[11].trim());
                    alipayRefundBill.setRechargeMethod(record[12].trim());
                    alipayRefundBill.setMchtName(record[13].trim());
                    alipayRefundBill.setStoreId(record[14].trim());
                    alipayRefundBill.setStoreName(record[15].trim());
                    alipayRefundBill.setCouponId(record[16].trim());
                    alipayRefundBill.setCouponTemplate(record[17].trim());
                    alipayRefundBill.setCardBin(record[18].trim());
                    //alipayRefundBill.setDistrictName(record[19].trim());
                    //alipayRefundBill.setDistrictStoreName(record[20].trim());
                    dataList.add(alipayRefundBill);
                    if(dataList.size()>10000){
                        alipayBillTaskMapper.addRefundBillBatchOrUpdate(dataList);
                        dataList.clear();
                    }
                }
            }

            if(dataList.size()>0){
                alipayBillTaskMapper.addRefundBillBatchOrUpdate(dataList);
                dataList.clear();
            }

            if(totalCount != totalDataSize){
                sendAlarmService.sendAlarmMail("250083682@qq.com","【异常】JOB-AlipayDtbankDailybillTask，获取退款记录数异常",totalCount + ":" + totalDataSize);
                throw new Exception("获取退款记录数【"+totalCount+"】【"+totalDataSize+"】不符！");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (inputStreamReader != null) {
                    inputStreamReader.close();
                }
                if(reader != null) {
                    reader.close();
                }
            } catch (Exception ioe){

            }
        }
        return dataList;
    }

    /**
     * 发放明细
     * @param file
     * @return
     */
    public List<String[]> readGrantList(File file){
        return null;
    }

}
